package com.example.demo.interceptor;

import com.example.demo.component.BpaThreadLocalUserAuth;
import com.example.demo.entity.CurrentUserInfo;
import com.example.demo.enums.RoleEnum;
import com.example.demo.exceptionmsg.BeaconExcepiton;
import com.example.demo.utils.CookieUtils;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
@Slf4j
public class ArthInterceptor extends HandlerInterceptorAdapter {

    @Value("${wfc-bpa-run-environment}")
    private String profile;

    private static final String DEV = "dev";

//    @Autowired
//    private RedissonClient redissonClient;

    @Autowired
    private MapperFacade orikaMapper;

    /**
     * 调用时间：Controller方法处理之前
     * 执行顺序：链式Intercepter情况下，Intercepter按照声明的顺序一个接一个执行
     * 若返回false，则中断执行，注意：不会进入afterCompletion
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //0.清除当前线程的用户信息
        BpaThreadLocalUserAuth.clearContext();

        //1.获取请求头信息,公共的部分放到请求头里
        //Integer currentRoleId = getCurrentRoleId(request);

        //1.1 //验证签名MD5({工号}{app_id}{时间戳}{app_secret})

        //2.获取用户信息
        CurrentUserInfo userInfo = getUserInfo(request, 1);

        if (userInfo == null) {
            throw new BeaconExcepiton("userinfo is null");
        }
        //3.保存到threadloacl
        BpaThreadLocalUserAuth.setContext(userInfo);
        return super.preHandle(request, response, handler);
    }

    /**
     * 调用前提：preHandle返回true
     * 调用时间：Controller方法处理完之后，DispatcherServlet进行视图的渲染之前，也就是说在这个方法中你可以对ModelAndView进行操作
     * 执行顺序：链式Intercepter情况下，Intercepter按照声明的顺序倒着执行。
     * 备注：postHandle虽然post打头，但post、get方法都能处理
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        //BpaThreadLocalUserAuth.clearContext();
        super.postHandle(request, response, handler, modelAndView);
    }

    /**
     * 调用前提：preHandle返回true
     * 调用时间：DispatcherServlet进行视图的渲染之后
     * 多用于清理资源
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
    }

    private CurrentUserInfo getUserInfo(HttpServletRequest request, Integer roleId) {
        // 获取token
        Cookie cookie = CookieUtils.getCookie(request, tokenName());
        String token = cookie == null ? "" : cookie.getValue();
        if (StringUtils.isEmpty(token)) {
            log.info("token为空!");
            return null;
        }

        // test环境从主数据获取用户信息
        if (profile.equals(DEV)) {
            return testProfile(token, roleId, request);
        }
        return null;
    }

    /**
     * 根据环境获取tokenName
     *
     * @return tokenKey
     */
    private String tokenName() {
        if (profile.equals(BpaConstants.PRI)) {
            return BpaConstants.PRI_TOKEN;
        } else {
            return BpaConstants.TOKEN;
        }
    }

    /**
     * test环境获取用户信息
     *
     * @param token   token
     * @param roleId  角色id
     * @param request request
     * @return userInfo
     */
    private CurrentUserInfo testProfile(String token, Integer roleId, HttpServletRequest request) {
        String userId = token.replace("portaltoken", "");

//        RBucket<Object> bucket = redissonClient.getBucket(MessageFormat.format(BpaConstants.USER_INFO, userId));
//        // 从缓存获取用户信息
//        Object obj = bucket.get();
//        log.info("从redis中读取user: " + obj);
//        ManageUser userInfo = null;
//        if (obj == null) {
//            log.info("从查询系统消息队列中读取user: " + userInfo);
//            // TODO: 2020/8/1 从数据库查询uesrInfo,然后存到redis
//
//            bucket.set(userInfo, 24 * 60 * 60, TimeUnit.SECONDS);
//        } else {
//            userInfo = (ManageUser) obj;
//        }
//        CurrentUserInfo currentUserInfo = orikaMapper.map(userInfo, CurrentUserInfo.class);
//        return currentUserInfo;
        return null;
    }

    /**
     * 获取角色id
     *
     * @param request request
     * @return roleId
     */
    private Integer getCurrentRoleId(HttpServletRequest request) {
        String roleStr = request.getHeader("role") == null ? "" : request.getHeader("role");
        RoleEnum roleEnum = RoleEnum.getByMenuCode(roleStr);
        if (roleEnum != null) {
            return roleEnum.getValue();
        }
        return RoleEnum.NONE.getValue();
    }

    class BpaConstants {
        public static final String PRI = "pri";
        public static final String PRI_TOKEN = "pri_token";
        public static final String TOKEN = "token";
        public static final String USER_INFO = "WFC_BPA:USER_INFO_{0}";

    }

}
